﻿using System;
using System.Collections.Generic;
using System.Linq;
using AMM.CustomClassLibrary;
using AMM.DataAccess.Finance;
using AMM.DataAccess.Store;
using AMM.Model;
using AMM.Model.Finance;

namespace AMM.Business.Finance {
    public class StatementProcessor : BaseProcessor {

        private int _pageSize;
        private StatementRepository _statementRepository;
        private ProcurementOrderRepository _procurementOrderRepository;

        public StatementProcessor(int pageSize = int.MaxValue) {
            this._pageSize = pageSize;
            this._statementRepository = new StatementRepository(pageSize);
            this._procurementOrderRepository = new ProcurementOrderRepository();
        }

        public Statement FetchStatementById(int statementId) {
            try {
                return this._statementRepository.FetchStatementById(statementId);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("获取指定月结单失败！");
            }
        }

        public List<StatementDetailsViewModel> FetchStatementDetailsViewModelList(int statementId) {
            try {
                Statement so = this.FetchStatementById(statementId);

                return this._statementRepository.FetchStatementByIdForView(statementId).StatementDetails.Select(x => {
                    return new StatementDetailsViewModel() {
                        Key = x.StatementDetailsId,
                        OrderCode = x.OrderCode,
                        OrderCreatedDateTime = x.OrderCreatedDateTime,
                        Amount = x.Amount,
                        StoreType = x.StoreType,
                        Remarks = x.Remarks
                    };
                }).ToList();
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("获取指定月结单失败！");
            }
        }

        public List<StatementViewModel> FetchStatementViewModelList(StatementSearchModel searchModel, int pageIndex = 1) {
            try {
                List<Statement> resultList = this._statementRepository.FetchStatementList(searchModel, pageIndex);
                return resultList.Select(x => {
                    return new StatementViewModel() {
                        Key = x.StatementId,
                        LastSurplus = x.LastSurplus,
                        NeededPay = x.NeededPay,
                        Paid = x.Paid,
                        Surplus = x.Surplus,
                        DatetimeSpan = string.Format("{0}-{1}", x.YearValue, x.MonthValue),
                        OrderStatus = MethodHelper.GetEnumsDescription(typeof(AuditStatus), x.Status),
                        AuditedBy = x.AuditedBy,
                        AuditedDatetime = x.AuditedDatetime,
                        CreatedBy = x.CreatedBy,
                        CreatedDatetime = x.CreatedDatetime,
                        VendorCode = x.Vendor.Code,
                        VendorName = x.Vendor.Name,
                        StatementCode = x.Code
                    };
                }).ToList();
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("获取月结单列表失败！");
            }
        }

        public void Insert(Statement statement) {
            try {
                statement.StatementId = Guid.NewGuid().GetHashCode();
                statement.CreatedDatetime = DateTime.Now;
                statement.Status = (int)AuditStatus.Waiting;
                statement.StatementDetails.ToList().ForEach(x => {
                    x.StatementDetailsId = Guid.NewGuid().GetHashCode();
                });
                this._statementRepository.Insert(statement);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("插入新月结单失败！");
            }
        }

        public void Update(Statement statement) {
            try {
                Statement oldStatement = this.FetchStatementById(statement.StatementId);
                if (!oldStatement.RowVersion.SequenceEqual(statement.RowVersion)) {
                    throw this.BuildException("更新月结单失败，数据不一致性错误！");
                }
                this._statementRepository.UpdateStatement(statement);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("更新月结单失败！");
            }
        }

        public void Audit(Statement statement) {
            try {
                Statement oldStatement = this.FetchStatementById(statement.StatementId);
                if (!oldStatement.RowVersion.SequenceEqual(statement.RowVersion)) {
                    throw this.BuildException("审核月结单失败，数据不一致性错误！");
                }
                statement.AuditedDatetime = DateTime.Now;
                this._statementRepository.UpdateStatement(statement);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("审核质检单失败！");
            }
        }

        public void Delete(Statement statement) {
            try {
                this._statementRepository.Delete(statement);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("删除月结单失败！");
            }
        }

        public void Delete(params int[] statementIds) {
            try {
                this._statementRepository.DeleteMultipleStatement(statementIds);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("删除月结单失败！");
            }
        }

        public int GetTheMaxFlowNumber(string startString) {
            try {
                return this._statementRepository.GetTheMaxFlowNumber(startString) + 1;
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("获取月结单最大流水号失败！");
            }
        }

        public void GenerateStatement(string code, string createdBy, DateTime dt) {
            try {
                this._statementRepository.GenerateStatement(code, createdBy, dt);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("生成月结单失败！");
            }
        }

        public bool CheckStatementPrerequisite(DateTime dt) {
            try {
                return this._statementRepository.CheckStatementPrerequisite(dt);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("生成月结单失败！");
            }
        }
    }
}
